Brazilian E-Commerce Public Database by Olist https://www.kaggle.com/olistbr/brazilian-ecommerce?select=olist_order_items_dataset.csv
A database foi provida pela Olist, uma empresa de marketplace situada no Brasil. A Olist conecta pequenos negócios por todo o Brasil de uma forma simples. Vendedores conseguem vender seus produtos diretamente pela Olist Store, as entregas são feitas por meio de parceiros.
Quais são os principais fatores que alavancam o número de vendas? Quais os fatores que impactam na avaliação do cliente?
import pandas as pd
import numpy as np
import holoviews as hv
import geoviews as gv
import datashader as ds
from warnings import simplefilter
from colorcet import fire, rainbow, bgy, bjy, bkr, kb, kr
from datashader.colors import colormap_select, Greys9
from holoviews.streams import RangeXY
from holoviews.operation.datashader import datashade, dynspread, rasterize
from bokeh.io import push_notebook, show, output_notebook
from datashader.utils import lnglat_to_meters as webm
from datashader import transfer_functions as tf
# Versões dos pacotes usados neste jupyter notebook
%reload_ext watermark
%watermark -a "Herikc Brecher e João Hutner" --iversions
Author: Herikc Brecher e João Hutner pandas : 1.2.4 holoviews : 1.14.5 geoviews : 1.9.1 numpy : 1.19.5 datashader: 0.13.0
simplefilter(action='ignore', category=FutureWarning)
# Ambiente para Analise Geoespacial
output_notebook()
hv.extension('bokeh')
%opts Overlay [width=800 height=600 toolbar='above' xaxis=None yaxis=None]
%opts QuadMesh [tools=['hover'] colorbar=True] (alpha=0 hover_alpha=0.2)
T = 0.05
PX = 1
# Seed de Aleatoriedade
seed_ = 194
np.random.seed(seed_)
# Carregamento de todos datasets
dtCustomers = pd.read_csv('../data/olist_customers_dataset.csv', encoding = 'utf8', dtype={'customer_zip_code_prefix': str})
dtGeolocation = pd.read_csv('../data/olist_geolocation_dataset.csv', encoding = 'utf8', dtype={'geolocation_zip_code_prefix': str})
dtOrderItems = pd.read_csv('../data/olist_order_items_dataset.csv', encoding = 'utf8')
dtOrderPayments = pd.read_csv('../data/olist_order_payments_dataset.csv', encoding = 'utf8')
dtOrderReviews = pd.read_csv('../data/olist_order_reviews_dataset.csv', encoding = 'utf8')
dtOrders = pd.read_csv('../data/olist_orders_dataset.csv', encoding = 'utf8')
dtProducts = pd.read_csv('../data/olist_products_dataset.csv', encoding = 'utf8')
dtSellers = pd.read_csv('../data/olist_sellers_dataset.csv', encoding = 'utf8')
regioes = {
'AC': 'Norte',
'AL': 'Nordeste',
'AP': 'Norte',
'AM': 'Norte',
'BA': 'Nordeste',
'CE': 'Nordeste',
'DF': 'CentroOeste',
'ES': 'Sudeste',
'GO': 'CentroOeste',
'MA': 'Nordeste',
'MT': 'CentroOeste',
'MS': 'CentroOeste',
'MG': 'Sudeste',
'PA': 'Norte',
'PB': 'Nordeste',
'PR': 'Sul',
'PE': 'Nordeste',
'PI': 'Nordeste',
'RJ': 'Sudeste',
'RN': 'Nordeste',
'RS': 'Sul',
'RO': 'Norte',
'RR': 'Norte',
'SC': 'Sul',
'SP': 'Sudeste',
'SE': 'Nordeste',
'TO': 'Norte'
}
dtCustomers['regiao'] = dtCustomers['customer_state'].copy()
dtCustomers = dtCustomers.replace({'regiao': regioes})
dtCustomers.head()
| customer_id | customer_unique_id | customer_zip_code_prefix | customer_city | customer_state | regiao | |
|---|---|---|---|---|---|---|
| 0 | 06b8999e2fba1a1fbc88172c00ba8bc7 | 861eff4711a542e4b93843c6dd7febb0 | 14409 | franca | SP | Sudeste |
| 1 | 18955e83d337fd6b2def6b18a428ac77 | 290c77bc529b7ac935b93aa66c333dc3 | 09790 | sao bernardo do campo | SP | Sudeste |
| 2 | 4e7b3e00288586ebd08712fdd0374a03 | 060e732b5b29e8181a18229c7b0b2b5e | 01151 | sao paulo | SP | Sudeste |
| 3 | b2b6027bc5c5109e529d4dc6358b12c3 | 259dac757896d24d7702b9acbbff3f3c | 08775 | mogi das cruzes | SP | Sudeste |
| 4 | 4f2d8ab171c80ec8364f7c12e35b23ad | 345ecd01c38d18a9036ed96c73b8d066 | 13056 | campinas | SP | Sudeste |
dtSellers['regiao'] = dtSellers['seller_state'].copy()
dtSellers = dtCustomers.replace({'regiao': regioes})
dtSellers.head()
| customer_id | customer_unique_id | customer_zip_code_prefix | customer_city | customer_state | regiao | |
|---|---|---|---|---|---|---|
| 0 | 06b8999e2fba1a1fbc88172c00ba8bc7 | 861eff4711a542e4b93843c6dd7febb0 | 14409 | franca | SP | Sudeste |
| 1 | 18955e83d337fd6b2def6b18a428ac77 | 290c77bc529b7ac935b93aa66c333dc3 | 09790 | sao bernardo do campo | SP | Sudeste |
| 2 | 4e7b3e00288586ebd08712fdd0374a03 | 060e732b5b29e8181a18229c7b0b2b5e | 01151 | sao paulo | SP | Sudeste |
| 3 | b2b6027bc5c5109e529d4dc6358b12c3 | 259dac757896d24d7702b9acbbff3f3c | 08775 | mogi das cruzes | SP | Sudeste |
| 4 | 4f2d8ab171c80ec8364f7c12e35b23ad | 345ecd01c38d18a9036ed96c73b8d066 | 13056 | campinas | SP | Sudeste |
dtGeolocation['regiao'] = dtGeolocation['geolocation_state'].copy()
dtGeolocation = dtGeolocation.replace({'regiao': regioes})
dtGeolocation.head()
| geolocation_zip_code_prefix | geolocation_lat | geolocation_lng | geolocation_city | geolocation_state | regiao | |
|---|---|---|---|---|---|---|
| 0 | 01037 | -23.545621 | -46.639292 | sao paulo | SP | Sudeste |
| 1 | 01046 | -23.546081 | -46.644820 | sao paulo | SP | Sudeste |
| 2 | 01046 | -23.546129 | -46.642951 | sao paulo | SP | Sudeste |
| 3 | 01041 | -23.544392 | -46.639499 | sao paulo | SP | Sudeste |
| 4 | 01035 | -23.541578 | -46.641607 | sao paulo | SP | Sudeste |
agg_name = 'geolocation_zip_code_prefix'
def plot_map(data, label, agg_data, agg_name, cmap):
url="http://server.arcgisonline.com/ArcGIS/rest/services/Canvas/World_Dark_Gray_Base/MapServer/tile/{Z}/{Y}/{X}.png"
geomap = gv.WMTS(url)
points = hv.Points(gv.Dataset(data, kdims=['x', 'y'], vdims=[agg_name]))
agg = datashade(points, element_type=gv.Image, aggregator=agg_data, cmap=cmap)
zip_codes = dynspread(agg, threshold=T, max_px=PX)
hover = hv.util.Dynamic(rasterize(points, aggregator=agg_data, width=50, height=25, streams=[RangeXY]), operation=hv.QuadMesh)
hover = hover.options(cmap=cmap)
img = geomap * zip_codes * hover
img = img.relabel(label)
return img
dtGeolocation.head()
| geolocation_zip_code_prefix | geolocation_lat | geolocation_lng | geolocation_city | geolocation_state | regiao | |
|---|---|---|---|---|---|---|
| 0 | 01037 | -23.545621 | -46.639292 | sao paulo | SP | Sudeste |
| 1 | 01046 | -23.546081 | -46.644820 | sao paulo | SP | Sudeste |
| 2 | 01046 | -23.546129 | -46.642951 | sao paulo | SP | Sudeste |
| 3 | 01041 | -23.544392 | -46.639499 | sao paulo | SP | Sudeste |
| 4 | 01035 | -23.541578 | -46.641607 | sao paulo | SP | Sudeste |
dtGeolocation.dtypes
geolocation_zip_code_prefix object geolocation_lat float64 geolocation_lng float64 geolocation_city object geolocation_state object regiao object dtype: object
dtGeoMod = dtGeolocation.copy()
dtGeoMod['geolocation_zip_code_prefix_1_digits'] = dtGeoMod['geolocation_zip_code_prefix'].str[0:1]
dtGeoMod['geolocation_zip_code_prefix_2_digits'] = dtGeoMod['geolocation_zip_code_prefix'].str[0:2]
dtGeoMod['geolocation_zip_code_prefix_3_digits'] = dtGeoMod['geolocation_zip_code_prefix'].str[0:3]
dtGeoMod['geolocation_zip_code_prefix_4_digits'] = dtGeoMod['geolocation_zip_code_prefix'].str[0:4]
dtGeoMod.head()
| geolocation_zip_code_prefix | geolocation_lat | geolocation_lng | geolocation_city | geolocation_state | regiao | geolocation_zip_code_prefix_1_digits | geolocation_zip_code_prefix_2_digits | geolocation_zip_code_prefix_3_digits | geolocation_zip_code_prefix_4_digits | |
|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 01037 | -23.545621 | -46.639292 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0103 |
| 1 | 01046 | -23.546081 | -46.644820 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 |
| 2 | 01046 | -23.546129 | -46.642951 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 |
| 3 | 01041 | -23.544392 | -46.639499 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 |
| 4 | 01035 | -23.541578 | -46.641607 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0103 |
# Removendo outliers, iremos utilizar somente coordenadas no Brasil
# Pontos mais extremos do Brasil
dtGeoMod = dtGeoMod[dtGeoMod['geolocation_lat'] <= 5.27438888]
dtGeoMod = dtGeoMod[dtGeoMod['geolocation_lng'] >= -73.98283055]
dtGeoMod = dtGeoMod[dtGeoMod['geolocation_lat'] >= -33.75116944]
dtGeoMod = dtGeoMod[dtGeoMod['geolocation_lng'] <= -34.79314722]
x, y = webm(dtGeoMod['geolocation_lng'], dtGeoMod['geolocation_lat'])
dtGeoMod['x'] = pd.Series(x)
dtGeoMod['y'] = pd.Series(y)
dtGeoMod.head()
| geolocation_zip_code_prefix | geolocation_lat | geolocation_lng | geolocation_city | geolocation_state | regiao | geolocation_zip_code_prefix_1_digits | geolocation_zip_code_prefix_2_digits | geolocation_zip_code_prefix_3_digits | geolocation_zip_code_prefix_4_digits | x | y | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 01037 | -23.545621 | -46.639292 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0103 | -5.191862e+06 | -2.698137e+06 |
| 1 | 01046 | -23.546081 | -46.644820 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 | -5.192478e+06 | -2.698193e+06 |
| 2 | 01046 | -23.546129 | -46.642951 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 | -5.192270e+06 | -2.698199e+06 |
| 3 | 01041 | -23.544392 | -46.639499 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0104 | -5.191885e+06 | -2.697988e+06 |
| 4 | 01035 | -23.541578 | -46.641607 | sao paulo | SP | Sudeste | 0 | 01 | 010 | 0103 | -5.192120e+06 | -2.697646e+06 |
dtGeoMod['geolocation_zip_code_prefix'] = dtGeoMod['geolocation_zip_code_prefix'].astype(int)
dtGeoMod['geolocation_zip_code_prefix_1_digits'] = dtGeoMod['geolocation_zip_code_prefix_1_digits'].astype(int)
dtGeoMod['geolocation_zip_code_prefix_2_digits'] = dtGeoMod['geolocation_zip_code_prefix_2_digits'].astype(int)
dtGeoMod['geolocation_zip_code_prefix_3_digits'] = dtGeoMod['geolocation_zip_code_prefix_3_digits'].astype(int)
dtGeoMod['geolocation_zip_code_prefix_4_digits'] = dtGeoMod['geolocation_zip_code_prefix_4_digits'].astype(int)
É perceptivel que as regiões do Sul e Sudeste possuem um maior numero de vendas do que as demais, principalmente na região Sudeste.
plot_map(dtGeoMod, 'CEP no Brasil', ds.min(agg_name), agg_name, cmap=rainbow)
Focando no estado de São Paulo é perceptivel um grande numero de pedidos, representando aproximadamente 40% dos pedidos.
plot_map(dtGeoMod[dtGeoMod['geolocation_state'] == 'SP'], 'CEP no Estado de São Paulo', ds.min(agg_name), agg_name, cmap = rainbow)
plot_map(dtGeoMod[dtGeoMod['geolocation_city'] == 'sao paulo'], 'CEP na Cidade de São Paulo', ds.min(agg_name), agg_name, cmap = rainbow)
Focando no estado de Santa Catarina é claro uma diminuição brusca no numero de vendas, lembrando que SC é o 6 estado com mais vendas.
plot_map(dtGeoMod[dtGeoMod['geolocation_state'] == 'SC'], 'CEP no Estado de Santa Catarina', ds.min(agg_name), agg_name, cmap = rainbow)
plot_map(dtGeoMod[dtGeoMod['geolocation_city'] == 'itajai'], 'CEP na Cidade de Itajaí', ds.min(agg_name), agg_name, cmap = rainbow)
dtCustomers.head()
| customer_id | customer_unique_id | customer_zip_code_prefix | customer_city | customer_state | regiao | |
|---|---|---|---|---|---|---|
| 0 | 06b8999e2fba1a1fbc88172c00ba8bc7 | 861eff4711a542e4b93843c6dd7febb0 | 14409 | franca | SP | Sudeste |
| 1 | 18955e83d337fd6b2def6b18a428ac77 | 290c77bc529b7ac935b93aa66c333dc3 | 09790 | sao bernardo do campo | SP | Sudeste |
| 2 | 4e7b3e00288586ebd08712fdd0374a03 | 060e732b5b29e8181a18229c7b0b2b5e | 01151 | sao paulo | SP | Sudeste |
| 3 | b2b6027bc5c5109e529d4dc6358b12c3 | 259dac757896d24d7702b9acbbff3f3c | 08775 | mogi das cruzes | SP | Sudeste |
| 4 | 4f2d8ab171c80ec8364f7c12e35b23ad | 345ecd01c38d18a9036ed96c73b8d066 | 13056 | campinas | SP | Sudeste |
dtCustomersTemp = dtCustomers.copy()
dtCustomersTemp['customer_zip_code_prefix_3_digits'] = dtCustomersTemp['customer_zip_code_prefix'].str[0:3]
dtCustomersTemp['customer_zip_code_prefix_3_digits'] = dtCustomersTemp['customer_zip_code_prefix_3_digits'].astype(int)
dtGeoModBR = dtGeoMod.set_index('geolocation_zip_code_prefix_3_digits').copy()
dtOrderItems.head()
| order_id | order_item_id | product_id | seller_id | shipping_limit_date | price | freight_value | |
|---|---|---|---|---|---|---|---|
| 0 | 00010242fe8c5a6d1ba2dd792cb16214 | 1 | 4244733e06e7ecb4970a6e2683c13e61 | 48436dade18ac8b2bce089ec2a041202 | 2017-09-19 09:45:35 | 58.90 | 13.29 |
| 1 | 00018f77f2f0320c557190d7a144bdd3 | 1 | e5f2d52b802189ee658865ca93d83a8f | dd7ddc04e1b6c2c614352b383efe2d36 | 2017-05-03 11:05:13 | 239.90 | 19.93 |
| 2 | 000229ec398224ef6ca0657da4fc703e | 1 | c777355d18b72b67abbeef9df44fd0fd | 5b51032eddd242adc84c38acab88f23d | 2018-01-18 14:48:30 | 199.00 | 17.87 |
| 3 | 00024acbcdf0a6daa1e931b038114c75 | 1 | 7634da152a4610f1595efa32f14722fc | 9d7a1d34a5052409006425275ba1c2b4 | 2018-08-15 10:10:18 | 12.99 | 12.79 |
| 4 | 00042b26cf59d7ce69dfabb4e55b4fd9 | 1 | ac6c3623068f30de03045865e4e10089 | df560393f3a51e74553ab94004ba5c87 | 2017-02-13 13:57:51 | 199.90 | 18.14 |
dtOrdersTemp = dtOrders.merge(dtOrderItems, on='order_id')
dtOrdersTemp = dtOrdersTemp.merge(dtCustomersTemp, on='customer_id')
dtOrdersTemp = dtOrdersTemp.merge(dtOrderReviews, on = 'order_id')
dtFiltrado = dtOrdersTemp.groupby('customer_zip_code_prefix_3_digits')['price'].sum().to_frame()
revenue = dtGeoModBR.join(dtFiltrado)
agg_name = 'revenue'
revenue[agg_name] = revenue.price / 1000
Olhando para um heatmap de faturamento, é claro que os estados na região Sudeste possuem um faturamento superior em relação aos outros estados, ainda é visivel um faturamento alto na região Sul e uma distribuição grande pela região do Nordeste.
plot_map(revenue, 'Faturamento no Brasil (Em milhares de R$)', ds.mean(agg_name), agg_name, cmap=fire)
dtFiltrado = dtOrdersTemp.groupby('order_id').agg({'price': 'sum', 'customer_zip_code_prefix_3_digits': 'max'})
dtFiltrado = dtFiltrado.groupby('customer_zip_code_prefix_3_digits')['price'].mean().to_frame()
avg_ticket = dtGeoModBR.join(dtFiltrado)
agg_name = 'avg_ticket'
avg_ticket[agg_name] = avg_ticket.price
Já em relação ao Ticket Medio, é claro que as regiões do Nordeste possuem um ticket medio superior em relação ao Sudeste. É possível analisar que apesar de os estados do Nordeste possuirem um numero de pedidos menor, estão dispostos a realizar mais compras conjuntas. Isso pode se dar pelo baixo volume de compras que pode não ser representativo ou devido ao acumulo de diversos itens em unico pedido.
plot_map(avg_ticket, 'Ticket Medio em R$ no Brasil', ds.mean(agg_name), agg_name, cmap=bgy)
dtFiltrado = dtOrdersTemp.groupby('order_id').agg({'price': 'sum', 'freight_value': 'sum', 'customer_zip_code_prefix_3_digits': 'max'})
agg_name = 'freight_ratio'
dtFiltrado[agg_name] = dtFiltrado['freight_value'] / dtFiltrado['price']
dtFiltrado = dtFiltrado.groupby('customer_zip_code_prefix_3_digits')[agg_name].mean().to_frame()
freight_ratio = dtGeoModBR.join(dtFiltrado)
Mais uma vez é perceptivel que as regiões do Sudeste possuem uma taxa de transporte menor em relação ao pedido, isso se da pois a maioria das distribuidoras de carga e centrais de distribuição ficam localizadas nessa região. Assim é possível diminuir o valor do frete. Em contrapartida é visível que a região do Nordeste possui uma tendência a pagar mais caro pelo transporte, fazendo sentido com a relação feita anteriormente que os pedidos devem acumular mais produtos para compensar o valor do transporte.
plot_map(freight_ratio, 'Taxa de Transporte em Relação ao Pedido no Brasil', ds.mean(agg_name), agg_name, cmap=bgy)
dtOrdersTemp['order_delivered_customer_date'] = pd.to_datetime(dtOrdersTemp['order_delivered_customer_date'])
dtOrdersTemp['order_estimated_delivery_date'] = pd.to_datetime(dtOrdersTemp['order_estimated_delivery_date'])
dtOrdersTemp['order_delivered_carrier_date'] = pd.to_datetime(dtOrdersTemp['order_delivered_carrier_date'])
dtOrdersTemp['actual_delivery_time'] = dtOrdersTemp['order_delivered_customer_date'] - dtOrdersTemp['order_delivered_carrier_date']
dtOrdersTemp['actual_delivery_time'] = dtOrdersTemp['actual_delivery_time'].dt.days
dtFiltrado = dtOrdersTemp.groupby('customer_zip_code_prefix_3_digits')['actual_delivery_time'].mean().to_frame()
delivery_time = dtGeoModBR.join(dtFiltrado)
agg_name = 'avg_delivery_time'
delivery_time[agg_name] = delivery_time['actual_delivery_time']
Analisando o mapa abaixo é perceptivel que a região do Sudeste possuem uma entrega mais rapida, também é visualizado que as região do Sul possui um leve aumento no prazo de entrega. Já os estados da região Norte e Nordeste possuem um aumento consideravel, levando a um frete mais caro e mais demorado para essas regiões.
plot_map(delivery_time, 'Tempo Medio de Entrega em Dias no Brasil', ds.mean(agg_name), agg_name, cmap=bjy)
dtFiltrado = dtOrdersTemp.groupby('customer_zip_code_prefix_3_digits')['review_score'].mean().to_frame()
score = dtGeoModBR.join(dtFiltrado)
agg_name = 'avg_score'
score[agg_name] = score['review_score']
Analisando o grafico abaixo dos reviews realizados dos pedidos realizados no Brasil, é possível identificar que a região próxima ao Rio de Janeiro possui um acumulo maior de avaliações negativas, o mesmo serve para algumas regiões do Nordeste em sentido a região Norte. Já os pedidos na região Sul aparentam possuir uma maior taxa da avaliações positivas.
plot_map(score, 'Review Médio No Brasil', ds.mean(agg_name), agg_name, cmap=bgy)